package com.ysj.aipicturebe.manager.websocket.disruptor;

import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.ysj.aipicturebe.manager.websocket.model.PictureEditRequestMessage;
import com.ysj.aipicturebe.model.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;

/**
 * 图片编辑事件生产者
 */
@Component
@Slf4j
public class PictureEditEventProducer {

    @Resource
    private Disruptor<PictureEditEvent> pictureEditEventDisruptor;
    
    /**
     * 发布事件
     *
     * @param pictureEditRequestMessage
     * @param session
     * @param user
     * @param pictureId
     * 此方法的作用是将图片编辑事件发布到 Disruptor 的 RingBuffer 中。具体流程如下：
     * 获取 RingBuffer 实例，用于存储事件。
     * 获取下一个可用的序号，确保事件存储在正确的位置。
     * 根据序号获取事件对象，并设置事件的相关属性（如请求消息、会话、用户信息、图片 ID）。
     * 将事件发布到 RingBuffer，使其可以被消费者（如 PictureEditEventWorkHandler）处理。
     */
public void publishEvent(PictureEditRequestMessage pictureEditRequestMessage, WebSocketSession session, User user, Long pictureId) {
    // 获取 RingBuffer 实例，用于存储和处理事件
    RingBuffer<PictureEditEvent> ringBuffer = pictureEditEventDisruptor.getRingBuffer();

    // 获取下一个可用的序号，用于放置新的事件
    long next = ringBuffer.next();

    // 根据序号从 RingBuffer 中获取事件对象
    PictureEditEvent pictureEditEvent = ringBuffer.get(next);

    // 设置事件的图片编辑请求消息
    pictureEditEvent.setPictureEditRequestMessage(pictureEditRequestMessage);

    // 设置事件的 WebSocket 会话
    pictureEditEvent.setSession(session);

    // 设置事件的用户信息
    pictureEditEvent.setUser(user);

    // 设置事件的图片 ID
    pictureEditEvent.setPictureId(pictureId);

    // 发布事件到 RingBuffer，使其可被消费者处理
    ringBuffer.publish(next);
}

    /**
     * 优雅停机
     */
    /**
     * @PreDestroy 注解用于标记在 Spring 容器销毁 Bean 之前需要执行的方法。
     * 被标记的方法会在 Bean 被移除或应用关闭时自动调用，常用于资源释放、关闭连接等清理操作。
     * 在你的代码中，它确保在应用关闭时优雅地关闭 Disruptor，避免资源泄漏。
     */
    @PreDestroy
    public void destroy() {
        pictureEditEventDisruptor.shutdown();
    }
}

